package org.daochong.lang;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class ZIPUtils {
	public static final int minSize = 10;

	public static String compressString(String data) {
		return StringUtils.base64Encode(compressString(data.getBytes()));
	}

	public static String decompressString(String data) {
		return new String(decompressString(StringUtils.base64Decode(data)));
	}

	public static byte[] compressString(byte[] data) {
		if (data == null)
			throw new java.lang.IllegalArgumentException("the input is null");
		if (data.length < minSize) {
			throw new java.lang.IllegalArgumentException("the input length < "
					+ minSize);
		}
		byte[] compressed;
		ByteArrayOutputStream out = null;
		ZipOutputStream zout = null;
		try {
			out = new ByteArrayOutputStream();
			zout = new ZipOutputStream(out);
			zout.putNextEntry(new ZipEntry("0"));
			StringUtils.out(new ByteArrayInputStream(data), zout);
			zout.closeEntry();
			compressed = out.toByteArray();
		} catch (IOException e) {
			compressed = null;
		} finally {
			if (zout != null) {
				try {
					zout.close();
				} catch (IOException e) {
				}
			}
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
				}
			}
		}
		return compressed;
	}

	public static byte[] decompressString(byte[] compressed) {
		if (compressed == null)
			throw new java.lang.IllegalArgumentException("the input is null");
		ByteArrayOutputStream out = null;
		ByteArrayInputStream in = null;
		ZipInputStream zin = null;
		try {
			out = new ByteArrayOutputStream();
			in = new ByteArrayInputStream(compressed);
			zin = new ZipInputStream(in);
			zin.getNextEntry();
			StringUtils.out(zin, out);
			return out.toByteArray();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {

		}
		return null;
	}
	
	
	public static boolean compress(File in, File fileOut) {
		if (!in.exists())
			return false;
		ZipOutputStream zout = null;
		try {
			zout = new ZipOutputStream(new FileOutputStream(fileOut));
			compressZIP(zout, in, in.getPath().replaceAll("\\\\", "/"));
			zout.close();
			return true;
		} catch (IOException e) {

		}

		return false;
	}
	protected  final static void compressZIP(ZipOutputStream zout, File file,
			String path) {
		String p = file.getPath().replaceAll("\\\\", "/");
		if (!p.equals(path)) {
			p = p.replaceAll(path, "");
			if (p.length() > 0 && p.substring(0, 1).equals("/"))
				p = p.substring(1);
		} else {
			p = "";
		}
		if (file.isFile()) {
			if (file.canRead() && !file.isHidden()) {
				try {
					compressZIP(zout, new FileInputStream(file), p);
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}
			}
		} else if (file.isDirectory()) {
			File[] list = file.listFiles(new FileFilter() {
				public boolean accept(File file) {
					if (!file.canRead() || file.isHidden())
						return false;
					else
						return true;
				}
			});

			if (list != null) {
				for (File f : list) {
					compressZIP(zout, f, path);
				}
			}
		}
	}


	
	protected  final static void compressZIP(ZipOutputStream zout,
			InputStream in, String entryName) {
		try {
			String fn = new String(entryName.getBytes("UTF-8"),"ISO-8859-1").replaceAll(
					File.pathSeparator, "/");
			zout.putNextEntry(new ZipEntry(fn));
			StringUtils.out(in, zout);
			zout.closeEntry();
			zout.flush();
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	
	}
	
	public static void main(String[] args){
		long t = System.currentTimeMillis();
		compress(new File("D:\\temp\\test"),new File("D:\\tmp.zip"));
		long e = System.currentTimeMillis();
		
		System.out.println("T:"+(e-t));
		
	}
}
